﻿using MyProject01.Controller;
using MyProject01.RProjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MyProject01.TestCases
{

    enum UnitFunctions
    {
        LinearUnit,
        SigmoidUnit,
        TanhUnit,
        RectifiedLinearUnit,
        SoftplusUnit,
        SoftmaxUnit,
        MaxoutUnit
    };

    enum FineTuneFunctions
    {
        Backpropagation,
        Rpropagation,
        Minimizeclassifier,
        Minimizeautoencoder
    };

    class DarchNet : INetObject
    {
        public DarchObject Darch;

        public DarchNet (DarchObject obj)
        {
            Darch = obj;
        }

        public DataBlock[] Calculate(DataBlock[] inData)
        {
            DataBlock[] arr = new DataBlock[inData.Length];
            DataBlock res = Darch.Calculate(inData);
            for(int i=0;i<arr.Length;i++)
            {
                DataBlock d = new DataBlock(1);
                d[0] = res[i];
                arr[i] = d;
            }
            return arr;
        }

        public DataBlock Calculate(DataBlock inData)
        {
            return Darch.Calculate(inData);
        }
    }

    interface IDarchTrainerDataObject
    {
        DataBlock[] InData { get; }
        DataBlock[] SigData { get; }
    }
    class DarchTrainer : ITrainer
    {

        // net prarm
        private int _batchSize;
        private int _numEpochs;
        private double _stopClassError;
        private int _inputLength;
        private int _outputLength;
        private int[] _hidenNum;
        private int _rbm_numEpochs;
        private int _rbm_batchSize;
        private bool _rbm_lastLayer = true;

        private Thread _workThread;
        private IDarchTrainerDataObject _dataObject;
        private ITrainerEventHandler _handle;
        private int _epoch;
        private bool _isEnd;

        public string Description
        {
            get
            {
                return "Darch Trainer";
            }
        }

        public int Epoch
        {
            get
            {
                return _epoch;
            }
        }

        public int InputDataLength
        {
            get
            {
                return _dataObject.InData[0].Length;
            }

            set
            {
                return;
            }
        }

        public string Name
        {
            get
            {
                return "DarchTrainer";
            }
        }

        public int OutputDataLength
        {
            get
            {
                return _dataObject.SigData[0].Length;
            }

            set
            {
                return;
            }
        }
        public IDarchTrainerDataObject DataObject { set { _dataObject = value; } }

        public void Init()
        {
            // Todo nothing
        }

        public void SetEventHandler(ITrainerEventHandler handle)
        {
            _handle = handle;
        }

        public void Start()
        {
            lock (this)
                _isEnd = false;
            _workThread = new Thread(new ThreadStart(WorkMain));
            _workThread.Start();
        }

        public void Stop()
        {
            lock (this)
                _isEnd = true;
        }

        private void WorkMain()
        {
            DarchObject darchObj = new DarchObject();
            darchObj.Init(_dataObject.InData, _dataObject.SigData);
            _epoch = 1;
            while (true)
            {
                darchObj.Run();
#if true
                TrainingResult result = new TrainingResult();
                    result.Epoch = Epoch;
                    result.BestNetwork = new DarchNet(darchObj);
                    result.Fitness = _epoch;
                    _handle.Update(result);
#endif
                if (_epoch == 1)
                    darchObj.RbmNumEpochs = 0;
                _epoch++;

                if (_isEnd == true)
                    break;
            }


        }
    }
}
